﻿using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using System.Data;

using Sinacor.Infra.Service.Data;
using Sinacor.Infra.Service.Security.Authorization;
using Sinacor.Servico.Bovespa.BovespaBase.Util;
using Sinacor.Servico.Bovespa.Ordens;
using Sinacor.Servicos.Comum.Util.SGBD;


namespace Sinacor.Servico.Bovespa.Ordens.ResourceAccess
{
    public class LoteDigitacao : BaseResourceAccess
    {
        public LoteDigitacao()
            : base(AuthorizationContext.Current.CompanyId)
        {
        }

        /// <summary>
        /// Consultar se existe alguma digitação para o conjunto de Lotes recebidos por parâmetros
        /// 
        /// </summary>
        /// <param name="pLoteDigitacao"></param>
        /// <returns>true or false</returns>
        public bool  ConsultarLoteDigitacaoMultiplo(List<BusinessEntity.Parameter.ConsultarLoteDigitacao > pLoteDigitacao)
        {
            bool retorno = false;
            DbCommand dbCommand;

            StringBuilder sql = new StringBuilder();

            #region MontarSQL
            sql = new StringBuilder();
            sql.Append(@"select count(*) from TORDISORD Where Nr_Conjunto in ("); 

            #endregion

            foreach (BusinessEntity.Parameter.ConsultarLoteDigitacao  plote in pLoteDigitacao)
            {
                sql.Append(plote.NumeroConjunto + ","); 
            }
            
            sql.Append(")");
            sql.Replace(",)", ")");
            
            dbCommand = this.DataBase.GetSqlStringCommand(sql.ToString());
            retorno = (this.DataBase.ExecuteScalar(dbCommand).ToString() != "0");  



            return retorno; 
        }

        public void Inserir(BusinessEntity.LoteDigitacao pLoteDigitacao)
        {
            DbCommand dbCommand;
            StringBuilder sql = new StringBuilder();
            // Montando a string do sql 
            int NR_SEQDIS = obterSequencial(pLoteDigitacao.NumeroConjunto); 
            #region MontarSQL
            sql = new StringBuilder();
            sql.Append("INSERT INTO TORDISORD ");
            sql.Append("(NR_CONJUNTO ,");
            sql.Append(" NR_SEQDIS ,");
            sql.Append(" DT_DATMOV ,");
            sql.Append(" CD_CLIENTE ,");
            sql.Append(" DV_CLIENTE ,");
            sql.Append(" QT_CLIENTE ,");
            sql.Append(" PC_REDACR ,");
            sql.Append(" CD_CARLIQ ,");
            sql.Append(" CD_USUFIN ,");
            sql.Append(" CD_CLIFIN ,");
            sql.Append(" DV_CLIFIN ,");
            sql.Append(" VL_NEGOCIO ,");
            sql.Append(" IN_LIQUIDA ,");
            sql.Append(" PC_DISTRIB ,");
            sql.Append(" VL_DOLAR ,");
            sql.Append(" IN_EXTERNO ,");
            sql.Append(" IN_FOP ,");
            sql.Append(" DT_SISTEMA ");
            sql.Append(")");
            sql.Append("VALUES ");
            sql.Append("(:NR_CONJUNTO ,");
            sql.Append(" :NR_SEQDIS ,");
            sql.Append(" :DT_DATMOV ,");
            sql.Append(" :CD_CLIENTE ,");
            sql.Append(" :DV_CLIENTE ,");
            sql.Append(" :QT_CLIENTE ,");
            sql.Append(" :PC_REDACR ,");
            sql.Append(" :CD_CARLIQ ,");
            sql.Append(" :CD_USUFIN ,");
            sql.Append(" :CD_CLIFIN ,");
            sql.Append(" :DV_CLIFIN ,");
            sql.Append(" :VL_NEGOCIO ,");
            sql.Append(" :IN_LIQUIDA ,");
            sql.Append(" :PC_DISTRIB ,");
            sql.Append(" :VL_DOLAR ,");
            sql.Append(" :IN_EXTERNO ,");
            sql.Append(" :IN_FOP ,");
            sql.Append(" :DT_SISTEMA ");
            sql.Append(")");
            dbCommand = this.DataBase.GetSqlStringCommand(sql.ToString());
            #endregion

            // Adcionando Paramentros 
            #region AddParameter
                this.DataBase.AddInParameter(dbCommand, ":NR_CONJUNTO", DbType.Int64, pLoteDigitacao.NumeroConjunto);
                this.DataBase.AddInParameter(dbCommand, ":NR_SEQDIS", DbType.Int64, NR_SEQDIS);
                this.DataBase.AddInParameter(dbCommand, ":DT_DATMOV", DbType.Date, pLoteDigitacao.DataMovimento);
                this.DataBase.AddInParameter(dbCommand, ":CD_CLIENTE", DbType.Int32, pLoteDigitacao.CodigoCliente);
                this.DataBase.AddInParameter(dbCommand, ":DV_CLIENTE", DbType.Int32, pLoteDigitacao.DigitoVerificadorCliente);
                this.DataBase.AddInParameter(dbCommand, ":QT_CLIENTE", DbType.Int32, pLoteDigitacao.QuantidadeDestinadaCliente);
                this.DataBase.AddInParameter(dbCommand, ":PC_REDACR", DbType.Decimal, pLoteDigitacao.PercentualAcrescimo);
                this.DataBase.AddInParameter(dbCommand, ":CD_CARLIQ", DbType.Int32, pLoteDigitacao.CodigoCarteira);
                this.DataBase.AddInParameter(dbCommand, ":CD_USUFIN", DbType.Int32, (pLoteDigitacao.CodigoAgenteCustodia == string.Empty) ? null : pLoteDigitacao.CodigoAgenteCustodia);
                this.DataBase.AddInParameter(dbCommand, ":CD_CLIFIN", DbType.Int32, pLoteDigitacao.CodigoClienteCustodia);
                this.DataBase.AddInParameter(dbCommand, ":DV_CLIFIN", DbType.Int16, pLoteDigitacao.DigitoClienteCustodia);
                this.DataBase.AddInParameter(dbCommand, ":VL_NEGOCIO", DbType.Decimal, pLoteDigitacao.PrecoInformado);
                this.DataBase.AddInParameter(dbCommand, ":IN_LIQUIDA", DbType.String, Sinacor.Servico.Bovespa.BovespaBase.Util.Funcoes.ToUpper(Sinacor.Infra.Service.Common.EnumConverter.ToString<Sinacor.Servico.Bovespa.Ordens.BusinessEntity.Enum.TipoLiquidacaoDistribuicao?>(pLoteDigitacao.TipoLiquidacao)));
                this.DataBase.AddInParameter(dbCommand, ":PC_DISTRIB", DbType.Decimal, pLoteDigitacao.PercentualDistribuido);
                this.DataBase.AddInParameter(dbCommand, ":VL_DOLAR", DbType.Decimal, pLoteDigitacao.ValorDolar);
                this.DataBase.AddInParameter(dbCommand, ":IN_EXTERNO", DbType.String, pLoteDigitacao.IndicadorSistemaExterno);
                this.DataBase.AddInParameter(dbCommand, ":IN_FOP", DbType.String, pLoteDigitacao.IndicadorNaoLiquidacao);
                this.DataBase.AddInParameter(dbCommand, ":DT_SISTEMA", DbType.DateTime, DateTime.Today);
            #endregion

          

            this.DataBase.ExecuteNonQuery(dbCommand);
           // return NR_SEQDIS;
        }
        public void ExecutarDistribuicaoPercentual(BusinessEntity.LoteDigitacao pLoteDigitacao)
        {
            Object[] objcts = new Object[1]; 
            try
            {
                
                

                DbCommand dbCommand;
                StringBuilder sql = new StringBuilder();
                // Monta SQL 
                sql.Append("PR_DISTRI_CONJ.EXECUTA_DISTRI_PCT");
                dbCommand = this.DataBase.GetStoredProcCommand(sql.ToString());
                string dataOrdemFormatada = Sinacor.Servico.Bovespa.BovespaBase.Util.Funcoes.FormatarData(pLoteDigitacao.DataMovimento, "/");
                //Add paramento
                this.DataBase.AddInParameter(dbCommand, "P_DATMOV", DbType.AnsiString, dataOrdemFormatada); //CHAR IN
                this.DataBase.AddInParameter(dbCommand, "P_CONJUNTO", DbType.Int32, pLoteDigitacao.NumeroConjunto); //NUMBER IN

                this.DataBase.ExecuteNonQuery(dbCommand);
            }
            // ACERTADO COM TODOS POIS É A UNICA SOLUÇÃO POSSÍVEL , POIS O ERRO QUE VEM É DO ORACLE IRÁ SER ACERTADO NA PROXIMA INTERAÇÃO
            catch (System.Data.OracleClient.OracleException oraException)
            {
                 objcts[0] =  oraException.Message;
                 throw new BusinessException(109006, objcts);
         
            }
        }
        public void ExecutarDistribuicaoPreco(BusinessEntity.LoteDigitacao pLoteDigitacao)
        {
           Object[] objcts = new Object[1];
           try
           {
               DbCommand dbCommand;
               StringBuilder sql = new StringBuilder();

               string dataOrdemFormatada = Sinacor.Servico.Bovespa.BovespaBase.Util.Funcoes.FormatarData(pLoteDigitacao.DataMovimento, "/");
               // Monta SQL
               sql.Append("PR_DISTRI_CONJ.EXECUTA_DISTRI_PRECO");
               dbCommand = this.DataBase.GetStoredProcCommand(sql.ToString());
               //Add paramentro
               this.DataBase.AddInParameter(dbCommand, "P_DATMOV", DbType.String, dataOrdemFormatada); //CHAR IN
               this.DataBase.AddInParameter(dbCommand, "P_CONJUNTO", DbType.Int32, pLoteDigitacao.NumeroConjunto); //NUMBER IN

               this.DataBase.ExecuteNonQuery(dbCommand);
           }
           // ACERTADO COM TODOS POIS É A UNICA SOLUÇÃO POSSÍVEL , POIS O ERRO QUE VEM É DO ORACLE IRÁ SER ACERTADO NA PROXIMA INTERAÇÃO
           catch (System.Data.OracleClient.OracleException oraException)
           { 
               objcts[0] = oraException.Message;
               throw new BusinessException(109006, objcts);

           }
        }

        public void ExecutarDistribuicaoPrecoMedio(BusinessEntity.LoteDigitacao pLoteDigitacao)
        {
             Object[] objcts = new Object[1];
             try
             {

                 DbCommand dbCommand;
                 StringBuilder sql = new StringBuilder();

                 string dataOrdemFormatada = Sinacor.Servico.Bovespa.BovespaBase.Util.Funcoes.FormatarData(pLoteDigitacao.DataMovimento, "/");
                 // Monta SQL
                 sql.Append("PR_DISTRI_CONJ.EXECUTA_DISTRI");
                 dbCommand = this.DataBase.GetStoredProcCommand(sql.ToString());
                 //Add Paramentro 
                 this.DataBase.AddInParameter(dbCommand, "P_DATMOV", DbType.AnsiString, dataOrdemFormatada); //CHAR IN
                 this.DataBase.AddInParameter(dbCommand, "P_CONJUNTO", DbType.Int32, pLoteDigitacao.NumeroConjunto); //NUMBER IN

                 this.DataBase.ExecuteNonQuery(dbCommand);
             }
             // ACERTADO COM TODOS POIS É A UNICA SOLUÇÃO POSSÍVEL , POIS O ERRO QUE VEM É DO ORACLE IRÁ SER ACERTADO NA PROXIMA INTERAÇÃO
             catch (System.Data.OracleClient.OracleException oraException)
             {
                 objcts[0] = oraException.Message;
                 throw new BusinessException(109006, objcts);

             }
        }

        public void ExecutarDistribuicaoPrecoPorVolume(BusinessEntity.LoteDigitacao pLoteDigitacao)
        {
            
             Object[] objcts = new Object[1];
             try
             {

                 DbCommand dbCommand;
                 StringBuilder sql = new StringBuilder();
                 string dataOrdemFormatada = Sinacor.Servico.Bovespa.BovespaBase.Util.Funcoes.FormatarData(pLoteDigitacao.DataMovimento, "/");

                 //monta SQL
                 sql.Append("pOr_Distribui.pOr_Distr_Medio_Conj");
                 dbCommand = this.DataBase.GetStoredProcCommand(sql.ToString());

                 //Add Paramentro
                 this.DataBase.AddInParameter(dbCommand, "P_sDtNegocio", DbType.AnsiString, dataOrdemFormatada); //CHAR IN
                 this.DataBase.AddInParameter(dbCommand, "P_nConjunto", DbType.Int32, pLoteDigitacao.NumeroConjunto); //NUMBER IN
                 this.DataBase.AddInParameter(dbCommand, "P_sInOrigem", DbType.AnsiString, "P"); 




                 this.DataBase.ExecuteNonQuery(dbCommand);
             }
             // ACERTADO COM TODOS POIS É A UNICA SOLUÇÃO POSSÍVEL , POIS O ERRO QUE VEM É DO ORACLE IRÁ SER ACERTADO NA PROXIMA INTERAÇÃO
             catch (System.Data.OracleClient.OracleException oraException)
             {
                 objcts[0] = oraException.Message;
                 throw new BusinessException(109006, objcts);

             }
        }

        private int obterSequencial(Int64? iNumeroConjunto)
        {

            DbCommand dbCommand;
            StringBuilder sql = new StringBuilder();

            sql.AppendLine("Select MAX ( NR_SEQDIS ) + 1 From TORDISORD Where NR_CONJUNTO = " + iNumeroConjunto.ToString());
            dbCommand = this.DataBase.GetSqlStringCommand(sql.ToString());
            string result =  this.DataBase.ExecuteScalar(dbCommand).ToString();
            if (result.Trim().Length ==0 )
                return 1;
            else
                return Convert.ToInt32(result);
        }

        public List<BusinessEntity.LoteDigitacao> ConsultarLoteDigitacao(BusinessEntity.Parameter.ConsultarLoteDigitacao pConsultarLoteDigitacao)
        {

            DbCommand dbCommand;
            StringBuilder sql = new StringBuilder();

            #region Monta SQL
            sql.AppendLine("SELECT Distr.NR_CONJUNTO NumeroConjunto, "); //OK
            sql.AppendLine("Distr.NR_SEQDIS   NumeroSequenciaDigitacao, ");
            sql.AppendLine("Distr.DT_DATMOV   DataMovimento, ");
            sql.AppendLine("Distr.CD_CLIENTE  CodigoCliente,");
            sql.AppendLine("Distr.DV_CLIENTE  DigitoVerificadorCliente, ");
            sql.AppendLine("Distr.QT_CLIENTE  QuantidadeDestinadaCliente, ");
            sql.AppendLine("Distr.PC_REDACR   PercentualAcrescimo, ");
            sql.AppendLine("Distr.CD_CARLIQ   CodigoCarteira, ");
            sql.AppendLine("Distr.CD_USUFIN   CodigoAgenteCustodia, ");
            sql.AppendLine("Distr.CD_CLIFIN   CodigoClienteCustodia, ");
            sql.AppendLine("Distr.DV_CLIFIN   DigitoClienteCustodia, ");
            sql.AppendLine("Distr.VL_NEGOCIO  PrecoInformado, ");
            sql.AppendLine("Distr.IN_LIQUIDA  TipoLiquidacao, ");
            sql.AppendLine("Distr.PC_DISTRIB  PercentualDistribuido, ");
            sql.AppendLine("Distr.VL_DOLAR    ValorDolar, ");
            sql.AppendLine("Distr.IN_EXTERNO  IndicadorSistemaExterno, ");
            sql.AppendLine("Distr.IN_FOP      IndicadorNaoLiquidacao, ");
            sql.AppendLine("Cli.NM_APELIDO  NM_APELIDO ");
            sql.AppendLine(" FROM TORDISORD Distr");
            sql.AppendLine(" INNER JOIN TSCCLIBOL Cli ON Cli.CD_CLIENTE=DISTR.CD_CLIENTE "); 
            sql.AppendLine("WHERE NR_CONJUNTO = :pNumeroConjunto ");

            dbCommand = this.DataBase.GetSqlStringCommand(sql.ToString());
            this.DataBase.AddInParameter(dbCommand, "pNumeroConjunto", DbType.Int64, pConsultarLoteDigitacao.NumeroConjunto);
            #endregion

            #region Cria e retorna o list
            IDataReader reader = this.DataBase.ExecuteReader(dbCommand);

            List<BusinessEntity.LoteDigitacao> response = new List<BusinessEntity.LoteDigitacao>();

            while (reader.Read())
            {
                BusinessEntity.LoteDigitacao loteDigitacao = new BusinessEntity.LoteDigitacao();
                loteDigitacao.NumeroConjunto = Convert.ToInt64(reader["NumeroConjunto"]);
                loteDigitacao.NumeroSequenciaDigitacao = Convert.ToInt64(reader["NumeroSequenciaDigitacao"]);
                loteDigitacao.DataMovimento = Convert.ToDateTime(reader["DataMovimento"]);
                if (reader["CodigoCliente"].ToString().Trim().Length != 0)
                    loteDigitacao.CodigoCliente = Convert.ToInt32(reader["CodigoCliente"]);
                loteDigitacao.DigitoVerificadorCliente = Convert.ToInt32(reader["DigitoVerificadorCliente"]);
                if (reader["QuantidadeDestinadaCliente"].ToString().Trim().Length !=0 )
                    loteDigitacao.QuantidadeDestinadaCliente = Convert.ToDecimal(reader["QuantidadeDestinadaCliente"]);
                if (reader["PercentualAcrescimo"].ToString().Trim().Length != 0)
                    loteDigitacao.PercentualAcrescimo = Convert.ToDecimal(reader["PercentualAcrescimo"]);
                loteDigitacao.CodigoCarteira = Convert.ToInt32(reader["CodigoCarteira"]);
                if (reader["CodigoClienteCustodia"].ToString().Trim().Length != 0)
                    loteDigitacao.CodigoClienteCustodia = Convert.ToInt32(reader["CodigoClienteCustodia"]);
                if (reader["DigitoClienteCustodia"].ToString().Trim().Length != 0)
                    loteDigitacao.DigitoClienteCustodia = Convert.ToInt32(reader["DigitoClienteCustodia"]);
                if (reader["CodigoAgenteCustodia"].ToString().Trim().Length != 0)
                    loteDigitacao.CodigoAgenteCustodia = reader["CodigoAgenteCustodia"].ToString();
                if (reader["PrecoInformado"].ToString().Trim().Length != 0)
                    loteDigitacao.PrecoInformado = Convert.ToDecimal(reader["PrecoInformado"]);
                loteDigitacao.TipoLiquidacao = (BusinessEntity.Enum.TipoLiquidacaoDistribuicao?)Sinacor.Infra.Service.Common.EnumConverter.Parse<BusinessEntity.Enum.TipoLiquidacaoDistribuicao>
                                                   (Sinacor.Servicos.Comum.Util.SGBD.Funcoes.BDValorString(reader["TipoLiquidacao"])); ;
                if (reader["PercentualDistribuido"].ToString().Trim().Length != 0)
                    loteDigitacao.PercentualDistribuido = Convert.ToDecimal(reader["PercentualDistribuido"]);
                if (reader["ValorDolar"].ToString().Trim().Length != 0)
                    loteDigitacao.ValorDolar = Convert.ToDecimal(reader["ValorDolar"]);
                loteDigitacao.IndicadorSistemaExterno = reader["IndicadorSistemaExterno"].ToString();
                loteDigitacao.IndicadorNaoLiquidacao = reader["IndicadorNaoLiquidacao"].ToString();
                loteDigitacao.ApelidoCliente = reader["NM_APELIDO"].ToString();
                //loteDigitacao.ApelidoCliente = reader["ApelidoCliente"].ToString(); 
                response.Add(loteDigitacao);
            }
            #endregion

            return response;
        }

        public bool Excluir(BusinessEntity.Parameter.ExcluirLoteDigitacao pExcluirLoteDigitacao)
        {
            DbCommand dbCommand = this.DataBase.GetSqlStringCommand(
                @"DELETE TORDISORD
                  WHERE  NR_CONJUNTO = :NumeroConjunto
                  AND    NR_SEQDIS = :NumeroSequenciaDistribuicao"
            );

            this.DataBase.AddInParameter(dbCommand, "NumeroConjunto", DbType.Int32, pExcluirLoteDigitacao.NumeroConjunto);
            this.DataBase.AddInParameter(dbCommand, "NumeroSequenciaDistribuicao", DbType.Int32, pExcluirLoteDigitacao.NumeroSequenciaDistribuicao);
            this.DataBase.ExecuteNonQuery(dbCommand);

            return true;
        }
    }
}
